package com.java.jvm.memory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 导致线程不安全的因素有什么？
 * 1.多个线程在并发执行。
 * 2.多个线程有共享数据集(临界资源)上的竞争
 * 3.在共享数据集上的操作不是原子操作。
 * 如何保证线程安全呢？
 * 1.加锁
 * 2.取消共享
 */

class DateUtil{
      //SimpleDateFormat对象不是一个线程安全的对象(多线程共享使用时要考虑线程安全)
      private static SimpleDateFormat sdf1= new SimpleDateFormat("yyyy-MM-dd");
      public static synchronized Date parseString1(String dateStr) {
          try {
              return sdf1.parse(dateStr);
          } catch (ParseException e) {
              e.printStackTrace();
              return null;
          }
      }

    public static  Date parseString2(String dateStr) {
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return sdf2.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }
    //ThreadLocal是一个线程本地变量
    //用于操作线程中的一个容器,比方说向容器放数据，从容器取数据
    private static ThreadLocal<SimpleDateFormat> td=
            new ThreadLocal<SimpleDateFormat>();
    public static  Date parseString3(String dateStr) {
        try {
            //先从当前线程获取SimpleDateFormat对象
            SimpleDateFormat sdf3=td.get();
            //当前线程没有SimpleDateFormat对象，则创建对象并存储到当前线程。
            if(sdf3==null){
                sdf3=new SimpleDateFormat("yyyy-MM-dd");
                td.set(sdf3);
            }
            return sdf3.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }
    public static void remove(){
        td.remove();
    }
}
public class ThreadLocalTests {
    public static void main(String[] args) throws ParseException {
        for(int i=0;i<100;i++){
            new Thread(){
                @Override
                public void run() {
                   DateUtil.parseString2("2023-06-27");
                   //......
                   DateUtil.parseString2("2023-06-27");
                   DateUtil.parseString2("2023-06-27");
                   DateUtil.remove();//防止内存泄漏
                }
            }.start();
        }
    }

}
